package top.guochenchen.mydb.backend.dm.pageCache;              // 包声明

import java.io.File;                                          // 导入文件类
import java.io.FileNotFoundException;                         // 导入文件未找到异常
import java.io.RandomAccessFile;                              // 导入随机访问文件类
import java.nio.channels.FileChannel;                         // 导入文件通道类

import top.guochenchen.mydb.backend.dm.page.Page;               // 导入页面接口
import top.guochenchen.mydb.backend.utils.Panic;                // 导入panic工具
import top.guochenchen.mydb.common.Error;                       // 导入错误定义

/**
 * 定义页面缓存的接口，包括页面管理的基本操作和工厂方法。
 * 页面是数据库存储的基本单位，每个页面固定 8KB 大小。
 */
public interface PageCache {                                  // 页面缓存接口
    
    public static final int PAGE_SIZE = 1 << 13;             // 页面大小常量，8KB (2^13 = 8192字节)

    int newPage(byte[] initData);                             // 创建新页面，返回页面号
    Page getPage(int pgno) throws Exception;                  // 根据页面号获取页面
    void close();                                             // 关闭页面缓存
    void release(Page page);                                  // 释放页面引用

    void truncateByBgno(int maxPgno);                         // 截断数据库文件到指定页面号
    int getPageNumber();                                      // 获取当前数据库的页面总数
    void flushPage(Page pg);                                  // 强制刷新页面到磁盘

    public static PageCacheImpl create(String path, long memory) { // 静态工厂方法：创建新的页面缓存
        File f = new File(path+PageCacheImpl.DB_SUFFIX);      // 构造数据库文件路径
        try {
            if(!f.createNewFile()) {                          // 尝试创建新文件
                Panic.panic(Error.FileExistsException);       // 文件已存在则panic
            }
        } catch (Exception e) {                               // 捕获创建异常
            Panic.panic(e);                                   // panic处理
        }
        if(!f.canRead() || !f.canWrite()) {                   // 检查文件读写权限
            Panic.panic(Error.FileCannotRWException);         // 无权限则panic
        }

        FileChannel fc = null;                                // 初始化文件通道
        RandomAccessFile raf = null;                          // 初始化随机访问文件
        try {
            raf = new RandomAccessFile(f, "rw");              // 以读写模式打开文件
            fc = raf.getChannel();                            // 获取文件通道
        } catch (FileNotFoundException e) {                   // 捕获文件未找到异常
           Panic.panic(e);                                    // panic处理
        }
        return new PageCacheImpl(raf, fc, (int)memory/PAGE_SIZE); // 创建页面缓存实现，计算最大页面数
    }

    public static PageCacheImpl open(String path, long memory) { // 静态工厂方法：打开已存在的页面缓存
        File f = new File(path+PageCacheImpl.DB_SUFFIX);      // 构造数据库文件路径
        if(!f.exists()) {                                     // 检查文件是否存在
            Panic.panic(Error.FileNotExistsException);        // 不存在则panic
        }
        if(!f.canRead() || !f.canWrite()) {                   // 检查文件读写权限
            Panic.panic(Error.FileCannotRWException);         // 无权限则panic
        }

        FileChannel fc = null;                                // 初始化文件通道
        RandomAccessFile raf = null;                          // 初始化随机访问文件
        try {
            raf = new RandomAccessFile(f, "rw");              // 以读写模式打开文件
            fc = raf.getChannel();                            // 获取文件通道
        } catch (FileNotFoundException e) {                   // 捕获文件未找到异常
           Panic.panic(e);                                    // panic处理
        }
        return new PageCacheImpl(raf, fc, (int)memory/PAGE_SIZE); // 创建页面缓存实现
    }
}